#include <stdio.h>
#include "freertos/FreeRTOS.h"
#include "freertos/portmacro.h"
#include "freertos/task.h"
#include "freertos/queue.h"
#include "driver/gpio.h"
#include "driver/ledc.h"
#include "esp_err.h"
#include "esp_log.h"
#include "buzzer_driver.h"
#include "configuration.h"

#define LEDC_TIMER              LEDC_TIMER_0
#define LEDC_MODE               LEDC_LOW_SPEED_MODE
#define LEDC_OUTPUT_IO          PIN_NUM_BZ //PWM输出引脚
#define LEDC_CHANNEL            LEDC_CHANNEL_0
#define LEDC_DUTY_RES           LEDC_TIMER_13_BIT //占空比分辨率设置为13位
#define LEDC_DUTY               (4095) // 设置占空比50%. ((2 ** 13) - 1) * 50% = 4095
#define LEDC_FREQUENCY800HZ     (800) //800Hz
#define LEDC_FREQUENCY2KHZ      (2000) //2KHz
#define LEDC_FREQUENCY4KHZ      (4000) //4KHz

QueueHandle_t bz_queue = NULL;
static const char *tag = "Buzzer driver";

static void ledc_init(void)
{
    //LEDC PWM定时器配置
    ledc_timer_config_t ledc_timer = {
        .speed_mode       = LEDC_LOW_SPEED_MODE,//速度模式
        .timer_num        = LEDC_TIMER_0,//选用定时器0
        .duty_resolution  = LEDC_DUTY_RES,//占空比分辨率
        .freq_hz          = LEDC_FREQUENCY800HZ,  //PWM频率
        .clk_cfg          = LEDC_AUTO_CLK//时钟源
    };
    ESP_ERROR_CHECK(ledc_timer_config(&ledc_timer));
    
    //LEDC PWM通道配置
    ledc_channel_config_t ledc_channel = {
        .speed_mode     = LEDC_MODE,
        .channel        = LEDC_CHANNEL,
        .timer_sel      = LEDC_TIMER,
        .intr_type      = LEDC_INTR_DISABLE,
        .gpio_num       = LEDC_OUTPUT_IO,
        .duty           = 0, // Set duty to 0%
        .hpoint         = 0
    };
    ESP_ERROR_CHECK(ledc_channel_config(&ledc_channel));
}
/* 蜂鸣器任务 */
void buzzer_task()
{
    unsigned char ret_bz,cmd_rev;
    bool bu_busy_flag = false;

    while (true)
    {
        ret_bz = xQueueReceive(bz_queue,&cmd_rev,0);
        if(ret_bz)
        {
            if(!bu_busy_flag)
            {
                bu_busy_flag = true;//置忙
                ESP_LOGI(tag, "rev data:%d",cmd_rev);
                if (cmd_rev == DDIDI)//蜂鸣器 4KHz 短促 滴~ 滴
                {
                    ESP_ERROR_CHECK(ledc_set_freq(LEDC_MODE, LEDC_TIMER, LEDC_FREQUENCY4KHZ));//设置4KHz
                    ESP_ERROR_CHECK(ledc_set_duty(LEDC_MODE, LEDC_CHANNEL, LEDC_DUTY));//设置50占空比
                    ESP_ERROR_CHECK(ledc_update_duty(LEDC_MODE, LEDC_CHANNEL));//更新占空比设置 打开蜂鸣器
                    vTaskDelay(150 / portTICK_PERIOD_MS);
                    ESP_ERROR_CHECK(ledc_stop(LEDC_MODE, LEDC_CHANNEL, 0));//蜂鸣器停止 电平置0
                    vTaskDelay(200 / portTICK_PERIOD_MS);

                    ESP_ERROR_CHECK(ledc_set_duty(LEDC_MODE, LEDC_CHANNEL, LEDC_DUTY));//设置50占空比
                    ESP_ERROR_CHECK(ledc_update_duty(LEDC_MODE, LEDC_CHANNEL));
                    vTaskDelay(50 / portTICK_PERIOD_MS);
                    ESP_ERROR_CHECK(ledc_stop(LEDC_MODE, LEDC_CHANNEL, 0));//蜂鸣器停止 电平置0
                }
                else if (cmd_rev == DIDI)//蜂鸣器 800Hz 滴 滴
                {
                    ESP_ERROR_CHECK(ledc_set_freq(LEDC_MODE, LEDC_TIMER, LEDC_FREQUENCY800HZ));//设置800Hz
                    ESP_ERROR_CHECK(ledc_set_duty(LEDC_MODE, LEDC_CHANNEL, LEDC_DUTY));//设置50占空比
                    ESP_ERROR_CHECK(ledc_update_duty(LEDC_MODE, LEDC_CHANNEL));//更新占空比设置 打开蜂鸣器
                    vTaskDelay(200 / portTICK_PERIOD_MS);
                    ESP_ERROR_CHECK(ledc_stop(LEDC_LOW_SPEED_MODE, LEDC_CHANNEL, 0));//蜂鸣器停止 电平置0
                    vTaskDelay(200 / portTICK_PERIOD_MS);

                    ESP_ERROR_CHECK(ledc_set_duty(LEDC_MODE, LEDC_CHANNEL, LEDC_DUTY));//设置50占空比
                    ESP_ERROR_CHECK(ledc_update_duty(LEDC_MODE, LEDC_CHANNEL));//更新占空比设置 打开蜂鸣器
                    vTaskDelay(200 / portTICK_PERIOD_MS);
                    ESP_ERROR_CHECK(ledc_stop(LEDC_MODE, LEDC_CHANNEL, 0));//蜂鸣器停止 电平置0
                    vTaskDelay(500 / portTICK_PERIOD_MS);
                }
                else if (cmd_rev == DI)//蜂鸣器 4KHz 滴
                {
                    ESP_ERROR_CHECK(ledc_set_freq(LEDC_MODE, LEDC_TIMER, LEDC_FREQUENCY4KHZ));//设置4KHz
                    ESP_ERROR_CHECK(ledc_set_duty(LEDC_MODE, LEDC_CHANNEL, LEDC_DUTY));//设置50占空比
                    ESP_ERROR_CHECK(ledc_update_duty(LEDC_MODE, LEDC_CHANNEL));//更新占空比设置 打开蜂鸣器
                    vTaskDelay(50 / portTICK_PERIOD_MS);
                    ESP_ERROR_CHECK(ledc_stop(LEDC_MODE, LEDC_CHANNEL, 0));//蜂鸣器停止 电平置0
                }
                else if (cmd_rev == CONDI)//蜂鸣器持续响
                {
                    ESP_ERROR_CHECK(ledc_set_freq(LEDC_MODE, LEDC_TIMER, LEDC_FREQUENCY800HZ));//设置800Hz
                    ESP_ERROR_CHECK(ledc_set_duty(LEDC_MODE, LEDC_CHANNEL, LEDC_DUTY));//设置50占空比
                    ESP_ERROR_CHECK(ledc_update_duty(LEDC_MODE, LEDC_CHANNEL));//更新占空比设置 打开蜂鸣器
                }
                else if (cmd_rev == EXITDI)//关闭蜂鸣器持续响
                {
                    ESP_ERROR_CHECK(ledc_stop(LEDC_MODE, LEDC_CHANNEL, 0));//蜂鸣器停止 电平置0
                }
                bu_busy_flag = false;//置空闲
            }
        }
        vTaskDelay(200 / portTICK_PERIOD_MS);
    }
    
}
/* 蜂鸣器驱动初始化 */
void buzzer_init()
{
    gpio_set_level(PIN_NUM_BZ,0);//蜂鸣器控制引脚 电平置0

    //创建消息队列
    bz_queue = xQueueCreate(1,1);
    if(bz_queue == NULL) ESP_LOGE(tag, "bz_queue create fail.");

    ledc_init();

    //创建蜂鸣器任务
    xTaskCreate(buzzer_task, "buzzer_task", 2048, NULL, 15, NULL);
}